package dse.messages.singleversion;

import dse.*;
import dse.messages.*;
/**
 * Upon receiving one of these messages a node should do one of two things
 * (see GetDataObjectSharesTransaction for details on the entire share
 * downloading process).
 * 
 * 	1	Those nodes respond immediately with the share IF it has it.
 *	2	If it doesn't has the share, locate-clusters-with-data-object message to its super node.
 *		And from their it tries to find the share in different clusters.
 *
 * @author Aaron
 */
public class RequestShareMessageHandler 
extends MessageSender
implements MessageHandler
{
	
	private DataObject dobj;
	private int shareIndex;
	private MessagePurpose purpose;
	private ShareDownloader shareDownloader;
	
	public RequestShareMessageHandler (
			Experiment experiment, 
			DataObject dobj, 
			int shareIndex,
			MessagePurpose purpose,
			ShareDownloader shareDownloader
			)
	{
		super(experiment);
		
		this.dobj = dobj;
		this.shareIndex = shareIndex;
		this.purpose = purpose;
		this.shareDownloader = shareDownloader;
	}
	
	
	
	public boolean acceptMessage (
			Message message
			)
	{
		return true;
	}
	
	public void messageReceived (
			ExperimentRecorder recorder, 
			Message message,
			double timeLeft
			)
	{
		recorder.debug(this, "msgRcvd: " + message, timeLeft);
		if (message.messageType() != MessageType.RequestShare) {
			recorder.warn(
					"RequestShareMessageHandler recieved " + 
					message.messageType() + " message."
					);
			return;
		}			
		// What do we know about the share?
		Node receiver = message.to();
		receiver.setSequence(Math.max(receiver.getSequence()+1, message.from().getSequence()));		
		
		// Does the receiver have the share?
		if (receiver.isHosting(dobj, shareIndex) 
				//|| receiver.isCaching(dobj, shareIndex)
				)
		{
			// Then we need to send a new message BACK (thats why to and from
			// are reversed!
			receiver.sequence();
			Message m = super.createShareDataTransferMessage(
					receiver, message.from(), dobj, shareIndex, 
					purpose, shareDownloader
					);
			recorder.debug(this, "new msg: " + m, timeLeft);
			experiment.messageQueue().enqueueMessage(m, timeLeft);
			return;
		}
		else if(receiver.isUp())
		{
			shareDownloader.shareDownloadFailed(
					recorder, dobj, shareIndex, timeLeft
					);
			/*if(!experiment.nodesInRecentDataTransactionsList.containsKey(receiver))
			{
				int transId = experiment.getNewTransactionId();
				Transaction trans = null;
				
				if (experiment.configuration().getTestType() == TestType.DhtWithShares)
					trans = new GetDhtOneShareTransaction(experiment, transId, receiver, dobj, shareIndex);
				else// if(experiment.configuration().getTestType() == TestType.ClusterWithShares)
					trans = new GetOneShareTransaction(experiment, transId, receiver, dobj, shareIndex);
				experiment.transactions.add(trans);
				experiment.nodesInRecentDataTransactionsList.put(receiver, Experiment.currentPeriod);
				trans.start(recorder, timeLeft);
			}*/
		}
	}
	
	public void messageInterupted (
			ExperimentRecorder recorder, 
			Message message,
			double timeLeft
			)
	{
		recorder.debug(this, "msgIntrpt: " + message, timeLeft);
		shareDownloader.shareDownloadFailed(
				recorder, dobj, shareIndex, timeLeft
				);
	}
}
